package com.wink.admin.aspect;


import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.wink.admin.aspect.annotation.Log;
import com.wink.admin.common.enums.LogTypeEnum;
import com.wink.admin.common.event.SysLogEvent;
import com.wink.admin.entity.SysLog;
import com.wink.admin.utils.JsonUtil;
import com.wink.admin.utils.LoginUtils;
import com.wink.admin.utils.SpringContextHolder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Objects;

/**
 * 操作日志使用spring event异步入库
 *
 * @author L.cm
 */
@Aspect
@Slf4j
@Component
public class SysLogAspect {

    @Around("@annotation(syslog)")
    @SneakyThrows
    public Object around(ProceedingJoinPoint point, Log syslog) {
        String strClassName = point.getTarget().getClass().getName();
        String strMethodName = point.getSignature().getName();
        log.info("[类名]:{},[方法]:{}", strClassName, strMethodName);
        
        SysLog logVo = getSysLog();
        logVo.setTitle(syslog.value());

        // 发送异步日志事件
        Long startTime = System.currentTimeMillis();
        Object obj;

        try {
            obj = point.proceed();
        } catch (Exception e) {
            logVo.setType(LogTypeEnum.ERROR.getType());
            logVo.setException(e.getMessage());
            throw e;
        } finally {
            Long endTime = System.currentTimeMillis();
            logVo.setTime(endTime - startTime);
            SpringContextHolder.publishEvent(new SysLogEvent(logVo));
        }

        return obj;
    }

    private SysLog getSysLog() {
        HttpServletRequest request = ((ServletRequestAttributes) Objects
                .requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        SysLog log = new SysLog();
        log.setCreateBy(LoginUtils.getUserName());
        log.setType(LogTypeEnum.NORMAL.getType());
        log.setRemoteAddr(ServletUtil.getClientIP(request));
        log.setRequestUri(URLUtil.getPath(request.getRequestURI()));
        log.setMethod(request.getMethod());
        log.setUserAgent(request.getHeader("user-agent"));
        log.setParams(JsonUtil.toStr(request.getParameterMap()));
        log.setServiceId("admin");
        return log;
    }
}
